#include "ThreadPool.h"
#include "Configuration.h"

extern Configuration confd;

// 线程的入口函数
void* start_routine(void* arg)
{
    Thread* thread = (Thread*)arg;
    ThreadPool* tpool = thread->tpool;

    printf("Tread #%d started\n", thread->id);
    // 初始化 MySQL 连接
    thread->mysql = mysql_init(NULL);

    if (mysql_real_connect(thread->mysql, host, ...) == NULL) {
        // 进行错误处理
    } 


    // 调度线程
    pthread_mutex_lock(&tpool->count_lock);
    tpool->threads_alive++;
    pthread_mutex_unlock(&tpool->count_lock);

    while (tpool->keep_alive) {
        // 等待任务
        bsem_wait(&(tpool->jobs.has_jobs)); // 空闲线程阻塞在这儿
        if (tpool->keep_alive) {
            Job* job = jobqueue_pop(&tpool->jobs);
            if (job) {
                pthread_mutex_lock(&tpool->count_lock);
                tpool->threads_working++;
                pthread_mutex_unlock(&tpool->count_lock);

                // 执行任务
                job->function(job->arg, thread);

                free(job);

                pthread_mutex_lock(&tpool->count_lock);
                tpool->threads_working--;
                if (tpool->threads_working == 0) {
                    // 所有线程都处于空闲状态
                    pthread_cond_signal(&tpool->all_idle);
                }
                pthread_mutex_unlock(&tpool->count_lock);
            }
        }
    } // keep_alive == 0

    mysql_close(thread->mysql); // 关闭连接
                                
    pthread_mutex_lock(&tpool->count_lock);
    tpool->threads_alive--;
    pthread_mutex_unlock(&tpool->count_lock);

    printf("Thread #%d terminated\n", thread->id);
    return NULL;
}

void threadpool_init(ThreadPool* tpool, int n)
{
    tpool->threads = (Thread*) malloc(n * sizeof(Thread));
    jobqueue_init(&tpool->jobs);
    tpool->threads_alive = 0;
    tpool->threads_working = 0;
    tpool->keep_alive = 1;  // 希望线程存活
    pthread_mutex_init(&tpool->count_lock, NULL);
    pthread_cond_init(&tpool->all_idle, NULL);

    // 创建线程
    for (int i = 0; i < n; i++) {
        tpool->threads[i].id = i + 1;
        tpool->threads[i].mysql = NULL;
        tpool->threads[i].tpool = tpool;

        pthread_create(&tpool->threads[i].tid, NULL, start_routine, (void*)&tpool->threads[i]);
        // 分离线程
        pthread_detach(tpool->threads[i].tid);
    }
    // 等待所有线程启动
    while (tpool->threads_alive != n) {}
}

void threadpool_add_task(ThreadPool* tpool, void (*function)(void*, Thread*), void* arg)
{
    Job* newjob = (Job*)malloc(sizeof(Job));
    newjob->function = function;
    newjob->arg = arg;
    newjob->next = NULL;

    jobqueue_push(&tpool->jobs, newjob);
}

// 任务队列中没有任务，并且所有线程都处于空闲状态
void threadpool_wait(ThreadPool* tpool)
{
    pthread_mutex_lock(&tpool->count_lock);
    while (tpool->jobs.size || tpool->threads_working) {
        pthread_cond_wait(&tpool->all_idle, &tpool->count_lock);
    } // tpool->jobs.size == 0 && tpool->threads_working == 0
    pthread_mutex_unlock(&tpool->count_lock);
}

// 等所有线程把当前任务执行完，关闭线程 (任务队列中剩余的任务不执行的)
void threadpool_destroy(ThreadPool* tpool)
{
    // 启动关闭开关
    tpool->keep_alive = 0;
    // 等待所有线程结束
    while (tpool->threads_alive) {
       bsem_postall(&tpool->jobs.has_jobs); 
       sleep(1);
    }

    free(tpool->threads);
    jobqueue_destroy(&tpool->jobs);
    pthread_mutex_destroy(&tpool->count_lock);
    pthread_cond_destroy(&tpool->all_idle);
}


#ifdef THREADPOOL_TEST

void task(void* arg)
{
    int taskid = (int) arg;
    printf("#%lx: execute task %d\n", pthread_self(), taskid);
    sleep(1);   // 模拟执行任务
    printf("#%lx: task %d done\n", pthread_self(), taskid);
}

int main(int argc, char* argv[])
{
    ThreadPool tpool;
    threadpool_init(&tpool, 8);

    for(int i = 1; i <= 40; i++) {
        threadpool_add_job(&tpool, task, (void*)i);
    }

    // for(;;);
    // threadpool_wait(&tpool);
    
    // sleep(3);
    
    threadpool_wait(&tpool);
    threadpool_destroy(&tpool);
    return 0;
}

#endif
